import { contextMenu } from './context-menu-config';
import { cloneDeep } from 'lodash-es';
import { BsModalService } from '@farris/ui-modal';
import FdContainerBaseComponent from '../../common/containerBase/containerBase';
import { RowNode } from '@farris/ui-treetable';
import { DgControl } from '../../../../utils/dg-control';
import { ContextMenuManager } from '../../../../service/context-menu.manager';
import { ComponentFactoryResolver } from '@angular/core';
import { ControlContextMenuItem } from '../../../../entity/control-context-menu';
import { ControlService } from '../../../../service/control.service';
import { CreateDetailContainerService } from '../../splitter/context-menu/services/create-detail-container.service';
import { ListFilterFieldsEditorComponent } from '../../../filter/list-filter/property/editor/list-filter-fields-editor/list-filter-fields-editor.component';
import { IdService } from '@farris/ui-common';
import { WebCmdService } from '@farris/designer-services';
import { SplitLikeCardContainerContextMenuService } from './services/split-like-card-container';
import { ChildContainerFillService } from './services/child-container-fill';

const CREATE_DETAIL_CONTAINER_COMMAND = 'createDetailContainer';
const CREATE_GRAND_CONTAINER_COMMAND = 'createGrandContainer';
const CREATE_CHILD_CONTENT_COMMAND = 'addChildContent';
const SPLIT_LIKE_CARD_CONTAINER_COMMAND = 'splitLikeCardContentainer';
const CHILD_FILL_COMMAND = 'childContainerFill';

export class ContainerContextMenuManager extends ContextMenuManager {

    private resolver: ComponentFactoryResolver;
    private modalService: BsModalService;
    private controlService: any;



    constructor(cmp: FdContainerBaseComponent, rowNode: RowNode) {
        super(cmp, rowNode);

        this.resolver = this.serviceHost.getService('ComponentFactoryResolver');
        this.modalService = this.serviceHost.getService('ModalService');
        this.controlService = this.injector.get(ControlService);
    }
    /**
     * 过滤、修改控件树右键菜单
     */
    setContextMenuConfig() {
        let menuConfig = cloneDeep(contextMenu) as ControlContextMenuItem[];
        // 零代码不需要添加子级模板容器contextMenu中注掉
        if (!menuConfig) {
            return [];
        }

        menuConfig = this.assembleCreateChildContainerMenu(menuConfig);
        menuConfig = this.assembleCreateHtmlTemplateMenu(menuConfig);
        menuConfig = this.assembleCreateListFilterMenu(menuConfig);
        menuConfig = this.assembleSplitLikeCardContentainerMenu(menuConfig);
        menuConfig = this.assembleChildFillMenu(menuConfig);

        // 配置菜单点击事件
        this.addContextMenuHandle(menuConfig);

        return menuConfig;
    }
    /**
     * 点击控件树右键菜单
     */
    contextMenuClicked(e: { data: RowNode, menu: ControlContextMenuItem }) {
        const menu = e.menu;

        switch (menu.id) {
            // 添加从表区域
            case CREATE_DETAIL_CONTAINER_COMMAND: {
                this.createDetailContainer();
                break;
            }
            // 添加从从表区域
            case CREATE_GRAND_CONTAINER_COMMAND: {
                this.createGrandContainer();
                break;
            }
            // 拆分区块
            case SPLIT_LIKE_CARD_CONTAINER_COMMAND: {
                this.splitLikeCardContainer();
                break;
            }
            // 启用从表填充
            case 'enable' + CHILD_FILL_COMMAND: {
                this.enableChildContainerFill();
                break;
            }
            // 关闭从表填充
            case 'close' + CHILD_FILL_COMMAND: {
                this.closeChildContainerFill();
                break;
            }
            default: {
                // 添加子级
                if (menu.parentMenuId === CREATE_CHILD_CONTENT_COMMAND) {
                    this.createChildContent(menu);
                } else {
                    this.notifyService.warning('暂不支持');
                }
            }
        }
    }
    /**
     * 组装从表/从从表区域菜单
     * @param containerId 容器id
     * @param menuConfig 菜单
     */
    private assembleCreateChildContainerMenu(menuConfig: ControlContextMenuItem[]) {
        const templateOutlineSchema = this.domService.templateOutlineSchema || [];
        if (!templateOutlineSchema) {
            // console.log('未检测到模板配置数据');
            menuConfig = menuConfig.filter(menu =>
                menu.id !== CREATE_DETAIL_CONTAINER_COMMAND && menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
            return menuConfig;
        }
        const mainContainerSchema = templateOutlineSchema.find(schema => schema.type === 'MainContainer' || schema.type === 'RightMainContainer');

        if (!mainContainerSchema || !mainContainerSchema.children || mainContainerSchema.children.length < 1) {
            // console.log('未检测到主区域配置数据');
            menuConfig = menuConfig.filter(menu =>
                menu.id !== CREATE_DETAIL_CONTAINER_COMMAND && menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
            return menuConfig;
        }

        const rootCmp = this.domService.getComponentById('root-component');

        const mainContainer = this.domService.getNodeByIdPath(rootCmp, mainContainerSchema.path as string);

        // 滚动监听类表单，不支持创建从表区域
        const scrollSpyContainer = mainContainer.contents.find(co => co.type === DgControl.Scrollspy.type);
        if (scrollSpyContainer) {
            menuConfig = menuConfig.filter(menu =>
                menu.id !== CREATE_DETAIL_CONTAINER_COMMAND && menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
            return menuConfig;
        }

        const likeCardCotainer = mainContainer.contents.find(co => co.type === DgControl.ContentContainer.type && co.isLikeCardContainer);
        let detailContainerParentElement;
        if (likeCardCotainer) {
            detailContainerParentElement = likeCardCotainer;
        } else {
            detailContainerParentElement = mainContainer;
        }

        if (detailContainerParentElement.id !== this.cmpInstance.id) {
            // console.log('当前节点不是主区域节点');
            menuConfig = menuConfig.filter(menu =>
                menu.id !== CREATE_DETAIL_CONTAINER_COMMAND && menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
            return menuConfig;
        }

        // 判断是否包含从表区域
        const detailSchema = mainContainerSchema.children[1];
        const detailSectionContainer = this.domService.getNodeByIdPath(rootCmp, detailSchema.path as string);
        const hasDetailContainer = !!detailSectionContainer && detailSchema.id === 'child-grid';

        if (hasDetailContainer) {
            // 存在从表区域
            menuConfig = menuConfig.filter(menu => menu.id !== CREATE_DETAIL_CONTAINER_COMMAND);

            if (mainContainerSchema.children.length > 2) {
                const grandsonSchema = mainContainerSchema.children[2];
                const grandsonSectionContainer = this.domService.getNodeByIdPath(rootCmp, grandsonSchema.path as string);
                const hasGrandsonDetailContainer = !!grandsonSectionContainer && grandsonSchema.id === 'grandson-grid';
                if (hasGrandsonDetailContainer) {
                    // 存在从从表区域
                    menuConfig = menuConfig.filter(menu => menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
                }
            } else {
                // schema中没有声明从从表区域，则不能创建从从表区域
                menuConfig = menuConfig.filter(menu => menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
            }

        } else {
            // 不存在从表区域，则不能创建从从表区域
            menuConfig = menuConfig.filter(menu => menu.id !== CREATE_GRAND_CONTAINER_COMMAND);
        }

        return menuConfig;
    }

    /**
     * 创建从表区域
     */
    private createDetailContainer() {
        const controlService = this.injector.get(ControlService);

        const createDetailService = new CreateDetailContainerService(this.domService, controlService);

        const templateOutlineSchema = this.domService.templateOutlineSchema || [];
        const mainContainerSchema = templateOutlineSchema.find(schema =>
            schema.type === 'MainContainer' || schema.type === 'RightMainContainer');

        createDetailService.createDetailContainer(mainContainerSchema, 'child-grid');

        this.notifyService.success('已添加从表区域');
        this.refreshFormService.refreshFormDesigner.next(this.cmpInstance.id);
    }

    /**
     * 创建从从表区域
     */
    private createGrandContainer() {
        const controlService = this.injector.get(ControlService);

        const createDetailService = new CreateDetailContainerService(this.domService, controlService);

        const templateOutlineSchema = this.domService.templateOutlineSchema || [];
        const mainContainerSchema = templateOutlineSchema.find(schema =>
            schema.type === 'MainContainer' || schema.type === 'RightMainContainer');

        createDetailService.createDetailContainer(mainContainerSchema, 'grandson-grid');

        this.notifyService.success('已添加从从表区域');
        this.refreshFormService.refreshFormDesigner.next(this.cmpInstance.id);
    }

    /**
     * 组装创建html模板菜单
     * @param containerId 容器id
     * @param menuConfig 菜单
     */
    private assembleCreateHtmlTemplateMenu(menuConfig: ControlContextMenuItem[]) {
        const containerElement = this.cmpInstance.component;
        const addChildMenu = menuConfig.find(menu => menu.id === CREATE_CHILD_CONTENT_COMMAND);
        if (!addChildMenu || !addChildMenu.children) {
            return menuConfig;
        }

        const htmlMenu = addChildMenu.children.find(menu => menu.id === DgControl.HtmlTemplate.type);
        if (!htmlMenu) {
            return menuConfig;
        }

        // 模板规定的成对出现的层级结构，不允许插入其他节点。
        // 例如f-struct-wrapper 类的container，都是Container-Section成对出现，中间不允许插入节点；listFilterContainer-ListFilter 是成对出现的
        const elementClass = containerElement && containerElement.appearance && containerElement.appearance.class;
        if (elementClass && (elementClass.includes('f-struct-wrapper') || elementClass.includes('f-filter-container'))) {
            addChildMenu.children = addChildMenu.children.filter(menu => menu.id !== DgControl.HtmlTemplate.type);
        }

        // 页头的标题容器，不允许插入子级模板。
        const parent = this.cmpInstance.parent && this.cmpInstance.parent.component;
        const parentClass = parent && parent.appearance && parent.appearance.class || '';
        if (elementClass && elementClass.includes('f-title') && parentClass && parentClass.includes('f-page-header-base')) {
            addChildMenu.children = addChildMenu.children.filter(menu => menu.id !== DgControl.HtmlTemplate.type);
        }


        if (addChildMenu.children.length === 0) {
            menuConfig = menuConfig.filter(menu => menu.id !== CREATE_CHILD_CONTENT_COMMAND);
        }
        return menuConfig;

    }

    /**
     * 添加子级
     * @param containerId 容器节点id
     * @param menuItem 菜单项
     */
    private createChildContent(menuItem: ControlContextMenuItem) {
        switch (menuItem.id) {
            case DgControl.HtmlTemplate.type: {
                this.createHtmlTemplate();
                break;
            }
            case DgControl.ListFilter.type: {
                this.createListFilter();
                break;
            }
            default: {
                this.notifyService.warning('暂不支持');
            }
        }
    }
    /**
     * 创建html模板菜单
     * @param containerId 容器节点id
     */
    private createHtmlTemplate() {
        const controlService = this.injector.get(ControlService);

        const containerElement = this.cmpInstance.component;
        const htmlTemplateMetadata = controlService.getControlMetaData(DgControl.HtmlTemplate.type);
        htmlTemplateMetadata.id = 'html-' + Math.random().toString(36).slice(2, 6);

        if (!containerElement.contents) { containerElement.contents = []; }
        containerElement.contents.push(htmlTemplateMetadata);

        this.refreshFormService.refreshFormDesigner.next(containerElement.id);
        this.notifyService.success('添加成功');
    }


    /**
     * 组装创建前置任务菜单：限定在内置列表和管理列表的表单
     * @param containerId 容器id
     * @param menuConfig  菜单配置
     */
    private assembleCreateListFilterMenu(menuConfig: ControlContextMenuItem[]) {
        const containerElement = this.domService.domDgMap.get(this.cmpInstance.id);
        const addChildMenu = menuConfig.find(menu => menu.id === CREATE_CHILD_CONTENT_COMMAND);
        if (!addChildMenu || !addChildMenu.children) {
            return menuConfig;
        }

        const listFilterMenu = addChildMenu.children.find(menu => menu.id === DgControl.ListFilter.type);
        if (!listFilterMenu) {
            return menuConfig;
        }
        let showMenu = true;
        // 规定只有内置列表和管理列表的表单可以添加前置任务
        if (this.domService.module.templateId !== 'list-template') {
            showMenu = false;
        }

        // 规定只有标题区域可以添加前缀任务： header-nav 节点，带有'f-page-header-base'样式
        const elementClass = containerElement && containerElement.appearance && containerElement.appearance.class;
        if (!elementClass || !elementClass.includes('f-page-header-base')) {
            showMenu = false;
        }

        // 已经添加过筛选条，不能再次添加
        const listFilter = containerElement.contents && containerElement.contents.find(c => c.type === DgControl.ContentContainer.type &&
            c.appearance && c.appearance.class && c.appearance.class.includes('f-filter-container'));
        if (listFilter) {
            showMenu = false;
        }

        if (!showMenu) {
            addChildMenu.children = addChildMenu.children.filter(menu => menu.id !== DgControl.ListFilter.type);
            if (addChildMenu.children.length === 0) {
                menuConfig = menuConfig.filter(menu => menu.id !== CREATE_CHILD_CONTENT_COMMAND);
            }
        }

        return menuConfig;
    }

    /**
     * 创建前置任务（轻量筛选条）
     */
    private createListFilter() {
        const containerElement = this.cmpInstance.component;

        const compFactory = this.resolver.resolveComponentFactory(ListFilterFieldsEditorComponent);
        const compRef = compFactory.create(this.injector);
        const modalConfig = {
            title: '筛选条字段编辑器',
            width: 950,
            height: 500,
            showButtons: true,
            showMaxButton: true,
            buttons: compRef.instance.modalFooter
        };
        compRef.instance.value = [];
        compRef.instance.editorParams = {
            viewModelId: this.cmpInstance.viewModelId,
            controlSource: 'light'
        };
        const modalPanel = this.modalService.show(compRef, modalConfig);
        compRef.instance.closeModal.subscribe(() => {
            modalPanel.close();
        });
        compRef.instance.submitModal.subscribe((data) => {
            if (data && data.value) {

                // 1、组装筛选条容器和筛选条dom结构
                const listFilterContainer = this.controlService.getControlMetaData(DgControl.ContentContainer.type);
                const listFilterMetadata = this.controlService.getControlMetaData(DgControl.ListFilter.type);

                const idSuffix = Math.random().toString(36).slice(2, 6);
                Object.assign(listFilterContainer, {
                    id: 'list-filter-container-' + idSuffix,
                    appearance: {
                        class: 'f-filter-container f-content'
                    },
                    contents: [listFilterMetadata]
                });

                Object.assign(listFilterMetadata, {
                    id: 'list-filter-' + idSuffix,
                    filterList: data.value || [],
                    controlSource: 'light'
                });

                // 2、添加到标题的后面、工具栏前面
                if (!containerElement.contents) { containerElement.contents = []; }
                const titleIndex = containerElement.contents.findIndex(c => c.type === DgControl.ContentContainer.type &&
                    c.appearance && c.appearance.class && c.appearance.class.includes('f-title'));
                if (titleIndex > -1) {
                    containerElement.contents.splice(titleIndex + 1, 0, listFilterContainer);
                } else {
                    containerElement.contents.push(listFilterContainer);
                }


                // 3、预制筛选条查询命令
                const viewModel = this.domService.getViewModelById(this.cmpInstance.viewModelId);
                let newFilterCommandId;
                if (viewModel && viewModel.commands) {
                    if (!viewModel.commands.find(command => command.handlerName === 'Filter' && command.cmpId === '70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72')) {
                        newFilterCommandId = new IdService().generate();
                        const commandCode = `${viewModel.id.replace(/-/g, '')}Filter1`;
                        viewModel.commands.push(
                            {
                                id: newFilterCommandId,
                                code: commandCode,
                                name: '过滤列表数据1',
                                params: [
                                    {
                                        name: 'commandName',
                                        shownName: '过滤回调方法',
                                        value: ''
                                    },
                                    {
                                        name: 'frameId',
                                        shownName: '目标组件',
                                        value: ''
                                    }
                                ],
                                handlerName: 'Filter',
                                cmpId: '70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72',
                                shortcut: {},
                                extensions: []
                            }
                        );
                    }
                }

                // 4、预置筛选条查询数据的构件
                if (this.domService.module.webcmds) {
                    let loadDataCmd = this.domService.module.webcmds.find(cmd => cmd.id === '70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72');
                    if (!loadDataCmd) {
                        loadDataCmd = {
                            id: '70b4abd4-9f2c-4b7c-90e9-6ac6f4b74c72',
                            path: 'Gsp/Web/webcmp/bo-webcmp/metadata/webcmd',
                            name: 'ListController.webcmd',
                            refedHandlers: []
                        };
                        this.domService.module.webcmds.push(loadDataCmd);
                    }
                    if (newFilterCommandId) {
                        loadDataCmd.refedHandlers.push(
                            {
                                host: newFilterCommandId,
                                handler: 'Filter'
                            }
                        );

                    }
                }

                // 因为涉及到新增【ListController控制器】，所以这里需要获取控制器信息，方便交互面板展示命令数据
                this.webCmdService.checkCommands();

                this.notifyService.success('添加成功');
                this.refreshFormService.refreshFormDesigner.next();
            }
            modalPanel.close();
        });

    }

    /**
     * 组装拆分区块菜单
     */
    private assembleSplitLikeCardContentainerMenu(menuConfig: ControlContextMenuItem[]): ControlContextMenuItem[] {
        const serv = new SplitLikeCardContainerContextMenuService(this.injector, this.cmpInstance);

        const show = serv.checkCanSplitLikeCardContainer();

        if (!show) {
            menuConfig = menuConfig.filter(menu => menu.id !== SPLIT_LIKE_CARD_CONTAINER_COMMAND);
        }

        return menuConfig;
    }
    private splitLikeCardContainer() {
        const serv = new SplitLikeCardContainerContextMenuService(this.injector, this.cmpInstance);

        serv.splitLikeCardContainer();


        this.refreshFormService.refreshFormDesigner.next();
    }

    /**
     * 组装子表填充菜单
     */
    private assembleChildFillMenu(menuConfig: ControlContextMenuItem[]): ControlContextMenuItem[] {

        const serv = new ChildContainerFillService(this.injector, this.cmpInstance);
        return serv.assembleChildFillMenu(menuConfig);
    }


    /**
     * 启用子表填充
     */
    private enableChildContainerFill() {

        const serv = new ChildContainerFillService(this.injector, this.cmpInstance);
        serv.enableChildContainerFill(this.cmpInstance.component);

        this.refreshFormService.refreshFormDesigner.next();

    }
    /**
     * 关闭子表填充
     */
    private closeChildContainerFill() {
        const serv = new ChildContainerFillService(this.injector, this.cmpInstance);
        serv.closeChildContainerFill(this.cmpInstance.component);

        this.refreshFormService.refreshFormDesigner.next();
    }
}
